import functools
import json
import random
import string
import time
import requests

from app import db
from application.tools.comm import sendMsg
from captcha.image import ImageCaptcha
from flask import Blueprint, request, send_file, jsonify, redirect
from application.models.users.user import *
from application.tools.myjwt import mjwt
from application.tools.myredis import r

# 权限认证
def islogin(func):
    @functools.wraps(func)
    def wrapper():
        # 设置一个白名单，白名单是一个列表，列表里面有的数据就不需要进行token验证，如果没有就进行验证是否存在token
        whitelist = ['/user/getcode', '/user/sendSmsCode', '/user/login']
        # 获取前端访问的url
        url = request.path
        print('url================================', url)
        # 判断访问的接口是否存在白名单
        if url not in whitelist:
            # 从接口headers中获取token
            try:
                token = request.headers.get('token')
                print('token================================', token)
                # 调用封装好的jwt进行对比
                flag = mjwt.check_token(token)
                if flag == True:
                    # 如果通过就验证token是否过期
                    # 调用封装好的jwt进行解密
                    payload = mjwt.jwt_decode(token)
                    # 获取现在的时间
                    now = time.time()
                    # 获取token存入的有效期
                    tnow = payload['data']['exp']
                    # 判断token是否过期
                    if int(now)-int(tnow) > 3:
                        # 如果过期就返回用户登录信息过期

                        return jsonify({'code': '203', 'msg': '用户登录信息已过期'})
                else:
                    return jsonify({'code': '202', 'msg': 'token已经篡改'})
            except:
                return jsonify({'code': '201', 'msg': 'token不存在'})
        func()
        return func
    return wrapper


from application.tools.comm import get_ali_object
user_blue = Blueprint("userblue", __name__)
@user_blue.route("/reg")
def reg():
    return 123


# 获取图形验证码
@islogin
@user_blue.route("/getcode", methods=["GET"])
def getcode():
    img_code = "".join(random.sample(string.digits+string.ascii_letters, 4)) # 随机获取字符串+数字的的4个字符
    cap = ImageCaptcha() # 生成图形验证码
    img = cap.generate(img_code) # 使用生成图片
    # 从页面中获取uuid作为redis key
    uuid = str(request.args.get("uuid"))
    # 写入redis
    r.str_add(uuid, str(img_code), 60)

    return send_file(img, 'image/png')


# 发送短信验证码
@islogin
@user_blue.route('/sendSmsCode', methods=['POST'])
def sendSmsCode():
    data = request.data
    # 校验前端传来的参数
    if data:
        data = json.loads(data)
        # 获取3个参数
        mobile = data.get("mobile")
        img_code = data.get("piccode")
        uuid = data.get("uuid")
        print("img_code=======================", img_code, uuid, mobile)
        # 通过uuid查询
        value = r.str_get(uuid)
        print("value=======================", value)
        # 判断图形验证码是否存在
        if value:
            # 校验短信验证码
            if value.lower() == img_code.lower():
                # 验证短信验证码一分钟只能发送一次
                sms_code = r.str_get(mobile)
                # 判断手机号是否一分钟发送验证码
                if sms_code:
                    return jsonify({"code": 10013, "msg": "一分钟之内不能重复发送"})
                # 生成短信验证码
                scode = random.randint(000000, 999999)
                # 调用短信发送平台
                flag = sendMsg(mobile, scode)
                if flag == True:
                    # 将短信存入存入redis数据库中
                    print('scode: %s' % scode)
                    r.str_add(mobile, scode, 60)
                    a = r.str_get(mobile)
                    print("a==========:", a)
                    # 删除图形验证码
                    r.str_del(uuid)
                    # 返回结果
                    return jsonify({"code": 200, "msg": "发送成功"})
                else:
                    return jsonify({"code": 10001, "msg": "发送失败"})
            return jsonify({"code": 10012, "msg": "图形验证码错误"})

        else:
            return jsonify({"code": 10011, "msg": "图形验证码不存在"})
        # 校验图形验证码是否正确
    else:
        return jsonify({"code": 10010, "msg": "参数错误"})






# 注册和登录接口
@islogin
@user_blue.route("/login", methods=["POST"])
def login():
    # 接收前端参数
    data = request.data
    # 校验前端参数
    if data:
        data = json.loads(data)
        # 获取 手机号，验证码
        mobile = data.get("mobile")
        code = data.get("code")
        print('code======mobile', code, mobile)
        # 查询出redis数据库存储的验证码
        mcode = r.str_get(mobile)
        print('mcode======', mcode)
        # 校验验证码是否存在
        if mcode:
            # 校验短信验证码是否正确
            if code == mcode:
                # 查询手机号是否存在
                user = User.query.filter(User.mobile == mobile).first()
                # 判断是否获取过来数据
                if user:
                    # 删除redis中存储的短信验证码
                    r.str_del(mobile)
                # 如果不存在，就进行添加该用户
                else:
                    u = User(mobile=mobile, nikename=mobile)
                    db.session.add(u)
                    db.session.commit()
                    user = User.query.filter(User.mobile == mobile, User.nikename == mobile).first()
                # 用户信息生成token
                token = mjwt.jwt_encode(data={"data": {'uid': user.id, 'exp': int(time.time())}})
                # 返回信息给页面
                return jsonify({'code': 10000, 'token': token, 'userid': user.id})

            # 返回短信验证码错误
            else:
                return jsonify({"code": 10003, 'msg': '短信验证码错误'})
        # 如果验证码不存在返回结果
        else:
            return jsonify({"code": 10001, "meg": "短信验证码不存在"})
    # 返回参数错误
    return jsonify({"code": 10002, 'meg': "请输入，正确的数据"})


# 获取weibo地址
@user_blue.route("/getwburl")
def  getwburl():
    client_id="3674019597"
    redirect_uri="http://127.0.0.1:8000/user/weiboCallback/"
    url = "https://api.weibo.com/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s"%(client_id,redirect_uri)
    return jsonify({"code": 200, "url": url})


# weibo回调接口
@user_blue.route('/weiboCallback/')
def weiboCallback():
    # 获取code
    code = request.args.get('code')
    print("获取返回给自己的code", code)
    # 向access_token接口发起post请求
    data = {"client_id": '3674019597',"client_secret": "7ae99bc0d54ead29fc8d1b9fabd78587",
            "grant_type": "authorization_code",
            'redirect_uri': "http://127.0.0.1:8000/user/weiboCallback/", 'code': code}
    res = requests.post('https://api.weibo.com/oauth2/access_token', data=data)
    print(res.text)
    # 解析参数，token,uuid
    mes = json.loads(res.text)
    token = mes['access_token']
    uid = mes['uid']
    # 查询三方登陆中uid是否存在，如果存在，查询用户表，用用户信息生成token跳转到vue页面
    sql = "select user.id from user inner join sf_login on user.id=sf_login.userid where sf_login.uid='%s'"%(uid)
    user = db.session.execute(sql)
    # 判断是否查询到
    if user:
        for i in user:
            data = {"data": {"user.id": i[0], "exp": int(time.time())}}
            token = mjwt.jwt_encode(data)
            return redirect("http://localhost:8080/#/updateToken?userid="+str(i[0])+"&token="+token)

    # 不存在跳转到vue绑定页面，token uuid传递过去
    return redirect('http://localhost:8080/#/bindMobile?uid='+uid+"&token="+token)
# 绑定手机号
@user_blue.route("/bindMobile", methods=['POST'])
def bindMObile():
    data = json.loads(request.data)
    mobile = data.get('mobile')
    uid = data.get('uid')
    token = data.get('token')
    # 先查询用户表， 如果手机号存在
    print("mobile----uid-----token", mobile, uid, token)
    user = User.query.filter(User.mobile == mobile).first()
    print("获取user表中的数据：", user)
    print("-----------------------")
    print("-------------------")
    if user == None:
        print('存在执行的数据')
        u = User(mobile=mobile, nikename=mobile)
        db.session.add(u)
        db.session.commit()
        # 获取用户信息
        user = User.query.filter(User.mobile == mobile).first()
        print("打印的是获取到的user=======", user)
    #
    sfuser = SfLogin(userid=user.id, webfrom='wb', uid=uid, token=token)
    db.session.add(sfuser)
    db.session.commit()
    # 如果不存在， 写入user表
    # 获取userid 写入三方登录表， 生成token返回
    data = {'data': {'userid': user.id, 'exp': int(time.time())}}
    token = mjwt.jwt_encode(data)
    return jsonify({'userid': str(user.id), "token ": token})

# 购买vip生成订单
@user_blue.route("/buy", methods=["POST"])
def buy():
    data = json.loads(request.data)
    userid = data.get('userid')
    year = data.get('year')
    money = 200
    print("获取到的参数userid和会员年限year", userid, year)
    # 生成订单号
    order_no = str(int(time.time()))+str(userid)
    tmoney = money * int(year)
    # 写入vip计入表
    viprecord = VipRecord(order_no=order_no, userid=userid, year=year, money=tmoney, active_money=tmoney, status=1)
    db.session.add(viprecord)
    db.session.commit()
    # 支付， 返回支付url
    pay = get_ali_object()
    # 生成支付的url
    query_params = pay.direct_pay(
        subject="test",  # 商品简单描述
        out_trade_no=str(order_no),  # 用户购买的商品订单号（每次不一样） 20180301073422891
        total_amount=float(100.00),  # 交易金额(单位: 元 保留俩位小数)
    )
    pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）
    return jsonify({"code": 200, "url": pay_url})
import datetime
# 支付完成后的回调
@user_blue.route("/callback")
def callback():
    # 接收参数
    data = request.args
    datames = {k: v for k, v in data.items()}
    # 删除字段中key为sign的记录

    sign = datames.pop('sign')
    # 鉴权 订单号---流水号
    pay = get_ali_object()
    flag = pay.verify(datames, sign)
    print(flag)
    if flag == True:
        # 订单号
        order_no = datames.get('out_trade_no')
        print("参数为=============", order_no)

        # 支付宝流水号
        transaction_no = datames.get('trade_no')
        print("参数为=============", transaction_no)
        # 事务处理
        try:
            # 订单号更新订单表
            record = VipRecord.query.filter(VipRecord.order_no == order_no).first()
            print("获取的数据据为不知道=======", record.userid)
            record.status = 2
            record.transaction_no = transaction_no
            db.session.add(record)
            # 更新用户表
            print("id")
            a = User.query.filter(User.id == record.userid).update({"level": 2})
            print("aaaaaaaa", a)
            # 更新vip表
            vip = Vip.query.filter(Vip.userid == record.userid, Vip.status==1).first()
            print("vip123456777777777",vip)
            if vip is not None:
                # 结束时间+购买年限
                print("123456777777777")
                etime = vip.e_time.split("-")
                tyear = int(etime[0])+int(record.year)
                yearstr="-"
                etime[0] = str(tyear)
                retime = yearstr.join(etime)
                vip.e_time = retime
                db.session.add(vip)
            else:
                # nowyear = datetime.date.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%m:%s")
                # etime = nowyear.split("-")
                # tyear = int(etime[0]) + int(record.year)
                # etime[0] = str(tyear)
                # yearstr = "-"
                # retime = yearstr.join(etime)
                year = 365*int(record.year)
                retime = datetime.datetime.now()+datetime.timedelta(days=year)
                print("vip=============", retime)
                vip = Vip(userid=record.userid, s_time=datetime.datetime.now(), e_time=retime)
                print("vip=============", vip)
                db.session.add(vip)
            db.session.commit()
        except:
            db.session.rollback()
    else:
        print("鉴权失败")
    return "ok"



# 添加课程使用， 获取标签， 分类， 类别
@user_blue.route("/getTags")
def getTags():
    tags = Tags.query.all()
    tagslist = [{"id": i.id,"name": i.name}for i in tags]
    types = Ctype.query.all()
    typeslist = [{"id": i.id, "name": i.name}for i in types]
    ctype = CourseType.query.all()
    ctypelist = [{"id": i.id, "name": i.name}for i in ctype]

    return jsonify({"code": 200, "tags": tagslist, "types": typeslist, "clist": ctypelist})
